package config

import (
	"cr.org/utils"
	"fmt"
	"github.com/mitchellh/go-homedir"
	log "github.com/sirupsen/logrus"
	"github.com/spf13/pflag"
	"github.com/spf13/viper"
	"os"
	"path"
	"path/filepath"
	"strings"
)

var GlobalConfig *Config

type Config struct {
	DB     string  `json:"db,omitempty"`
	Server *Server `json:"server,omitempty"`
	Sqlite *Sqlite `json:"sqlite,omitempty"`
	Log    *Log    `json:"log,omitempty"`
	Pgsql  *Pgsql  `json:"pgsql,omitempty"`
	SqlLog bool    `json:"sql_log"`
}

type Log struct {
	Lv   string `json:"lv,omitempty"`
	Name string `json:"name,omitempty"`
}

type Sqlite struct {
	File string `json:"file,omitempty"`
}

type Pgsql struct {
	Addr     string `json:"addr,omitempty"`
	Port     int    `json:"port,omitempty"`
	Username string `json:"username,omitempty"`
	Password string `json:"password,omitempty"`
	DBName   string `json:"db_name,omitempty"`
}

type Server struct {
	Addr string `json:"addr,omitempty"`
	Cert string `json:"cert,omitempty"`
	Key  string `json:"key,omitempty"`
}

func init() {
	var err error
	GlobalConfig, err = SetupConfig()
	if err != nil {
		panic(err)
	}
	initLog()
}

func SetupConfig() (*Config, error) {
	p, err := os.Executable()
	if err != nil {
		log.Panic(err)
	}
	viper.SetConfigName("config")
	viper.SetConfigType("yml")
	viper.AddConfigPath(filepath.Dir(p))
	viper.AddConfigPath("$HOME/.next-terminal")
	viper.AddConfigPath(".")
	viper.AutomaticEnv()
	viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))

	pflag.String("db", "sqlite", "db mode")
	pflag.String("sqlite.file", path.Join("/usr/local/next-terminal/data", "sqlite", "next-terminal.db"), "sqlite db file")

	pflag.String("server.addr", "", "server listen addr")
	pflag.String("server.cert", "", "tls cert file")
	pflag.String("server.key", "", "tls key file")

	pflag.Parse()

	if err := viper.BindPFlags(pflag.CommandLine); err != nil {
		return nil, err
	}
	if err := viper.ReadInConfig(); err != nil {
		return nil, err
	}

	var config = &Config{
		DB: viper.GetString("db"),
		Sqlite: &Sqlite{
			File: viper.GetString("sqlite.file"),
		},
		Server: &Server{
			Addr: viper.GetString("server.addr"),
			Cert: viper.GetString("server.cert"),
			Key:  viper.GetString("server.key"),
		},
		Log: &Log{
			Lv:   viper.GetString("log.lv"),
			Name: viper.GetString("log.name"),
		},
		SqlLog: viper.GetBool("sql_log"),
	}
	if config.DB == "sqlite" {
		sqliteDir := filepath.Dir(config.Sqlite.File)
		sqliteDir, err := homedir.Expand(sqliteDir)
		if err != nil {
			return nil, err
		}
		if err := utils.MkdirP(sqliteDir); err != nil {
			s := fmt.Sprintf("创建文件夹 %v 失败: %v", sqliteDir, err.Error())
			panic(s)
		}
	}
	return config, nil
}
